The following example provides a property sheet containing all the available controls, including user-defined properties of a custom component.
Enter the following text into the IDL Editor:
; Property Sheet Demo
;
; This program contains these sections of code:
;
; (1) Definition of the IDLitTester class.
; (2) Methods for handling the user-defined data type.
; (3) Event handlers and main widget program.
;================================================
; (1) Definition of the IDLitTester class.
;------------------------------------------------
; IDLitTester
;
; Superclasses:
; IDLitComponent
;
; Subclasses:
; none
;
; Interfaces:
; IIDLProperty
;
; Intrinsic Methods:
; none (because it contains no objects)
;------------------------------------------------
; IDLitTester::Init
FUNCTION IDLitTester::Init, _REF_EXTRA = _extra
compile_opt idl2
; Initialize the superclass.
IF (self->IDLitComponent::Init() ne 1) THEN $
RETURN, 0
; Create IDLitTester.
; Nothing to do, for now.
; Register properties.
;
; * Only registered properties will show up in the property sheet.
; * <identifier> must match self.<identifier>.
self->RegisterProperty, 'BOOLEAN', /BOOLEAN , $
NAME = 'Boolean', DESCRIPTION = 'TRUE or FALSE'
self->RegisterProperty, 'COLOR', /COLOR, $
NAME = 'Color', DESCRIPTION = 'Color (RGB)'
self->RegisterProperty, 'USERDEF', USERDEF = '', $
NAME = 'User Defined', DESCRIPTION = 'User defined property'
self->RegisterProperty, 'NUMBER1', /INTEGER , $
NAME = 'Integer', DESCRIPTION = 'Integer in [-100, 100]', $
valid_range = [-100, 100]
self->RegisterProperty, 'NUMBER2', /FLOAT, $
NAME = 'Floating Point', DESCRIPTION = 'Number trackbar', $
valid_range = [-19.0D, 6.0D, 0.33333333333333D]
self->RegisterProperty, 'NUMBER3', /FLOAT, $
NAME = 'Floating Point', $
DESCRIPTION = 'Double in [-1.0, 1.0]', $
valid_range = [-1.0D, 1.0D]
self->RegisterProperty, 'LINESTYLE', /LINESTYLE, $
NAME = 'Line Style', DESCRIPTION = 'Line style'
self->RegisterProperty, 'LINETHICKNESS', /THICKNESS , $
NAME = 'Line Thickness', $
DESCRIPTION = 'Line thickness (pixels)'
self->RegisterProperty, 'STRINGOLA', /STRING , $
NAME = 'String', DESCRIPTION = 'Just some text'
self->RegisterProperty, 'SYMBOL', /SYMBOL , $
NAME = 'Symbol', DESCRIPTION = 'Symbol of some sort'
self->RegisterProperty, 'STRINGLIST', $
NAME = 'String List', DESCRIPTION = 'Enumerated list', $
enumlist = ['dog', 'cat', 'bat', 'rat', 'nat', $
'emu', 'owl', 'pig', 'hog', 'ant']
; Set any property values.
self->SetProperty, _EXTRA = _extra
RETURN, 1
END
;------------------------------------------------
; IDLitTester::Cleanup
PRO IDLitTester::Cleanup
compile_opt idl2
self->IDLitComponent::Cleanup
END
;------------------------------------------------
; IDLitTester::GetProperty
;
; Implemention for IIDLProperty interface
PRO IDLitTester::GetProperty, $
boolean = boolean, $
color = color, $
userdef = userdef, $
font = font, $
number1 = number1, $
number2 = number2, $
number3 = number3, $
linestyle = linestyle, $
linethickness = linethickness, $
stringola = stringola, $
stringlist = stringlist, $
symbol = symbol, $
_REF_EXTRA = _extra
compile_opt idl2
IF (arg_present(boolean)) THEN boolean = self.boolean
IF (arg_present(color)) THEN color = self.color
IF (arg_present(userdef)) THEN userdef = self.userdef
IF (arg_present(font)) THEN font = self.font
IF (arg_present(number1)) THEN number1 = self.number1
IF (arg_present(number2)) THEN number2 = self.number2
IF (arg_present(number3)) THEN number3 = self.number3
IF (arg_present(linestyle)) THEN linestyle = self.linestyle
IF (arg_present(linethickness)) $
THEN linethickness = self.linethickness
IF (arg_present(stringola)) THEN stringola = self.stringola
IF (arg_present(stringlist)) THEN stringlist = self.stringlist
IF (arg_present(symbol)) THEN symbol = self.symbol
; Superclass' properties:
IF (n_elements(_extra) gt 0) THEN $
self->IDLitComponent::GetProperty, _EXTRA = _extra
END
;------------------------------------------------
; IDLitTester::SetProperty
;
; Implementation for IIDLProperty interface
PRO IDLitTester::SetProperty, $
boolean = boolean, $
color = color, $
userdef = userdef, $
font = font, $
number1 = number1, $
number2 = number2, $
number3 = number3, $
linestyle = linestyle, $
linethickness = linethickness, $
stringola = stringola, $
stringlist = stringlist, $
symbol = symbol, $
_REF_EXTRA = _extra
compile_opt idl2
IF (n_elements(boolean) ne 0) THEN self.boolean = boolean
IF (n_elements(color) ne 0) THEN self.color = color
IF (n_elements(userdef) ne 0) THEN self.userdef = userdef
IF (n_elements(font) ne 0) THEN self.font = font
IF (n_elements(number1) ne 0) THEN self.number1 = number1
IF (n_elements(number2) ne 0) THEN self.number2 = number2
IF (n_elements(number3) ne 0) THEN self.number3 = number3
IF (n_elements(linestyle) ne 0) THEN self.linestyle = linestyle
IF (n_elements(linethickness) ne 0) THEN $
self.linethickness = linethickness
IF (n_elements(stringola) ne 0) THEN self.stringola = stringola
IF (n_elements(stringlist) ne 0) THEN self.stringlist = stringlist
IF (n_elements(symbol) ne 0) THEN self.symbol = symbol
self->IDLitComponent::SetProperty, _EXTRA = _extra
END
;------------------------------------------------
; IDLitTester__Define
PRO IDLitTester__Define
compile_opt idl2, hidden
struct = {$
IDLitTester, $
inherits IDLitComponent, $
boolean:0L, $
color:[0B,0B,0B], $
userdef:"", $
number1:0L, $
number2:0D, $
number3:0D, $
linestyle:0L, $
linethickness:0L, $
stringola:"", $
stringlist:0L, $
symbol:0L $
}
END
;================================================
; (2) Methods for handling the user-defined data type.
;------------------------------------------------
; UserDefEvent
;
; This procedure is just part of the widget code for
; the user defined property.
PRO UserDefEvent, e
IF (tag_names(e, /structure_name) eq 'WIDGET_BUTTON') $
THEN BEGIN
widget_control, e.top, get_uvalue = uvalue
widget_control, e.id, get_uvalue = numb_ness
propsheet = uvalue.propsheet
component = uvalue.component
identifier = uvalue.identifier
; Set the human readable value.
component->SetPropertyAttribute, $
identifier, userdef = numb_ness
; Set the real value of the component.
component->SetPropertyByIdentifier, identifier, numb_ness
WIDGET_CONTROL, propsheet, refresh_property = identifier
PRINT, 'Changed: ', uvalue.identifier, ': ', numb_ness
WIDGET_CONTROL, e.top, /destroy
ENDIF
END
;------------------------------------------------
; GetUserDefValue
;
; Creates widgets used to modify the user defined property's
; value. The value is actually set in UserDefEvent.
PRO GetUserDefValue, e
base = WIDGET_BASE(/row, title = 'Pick a Number', $
/modal, group_leader = e.top)
one = WIDGET_BUTTON(base, value = 'one', uvalue = 'oneness')
two = WIDGET_BUTTON(base, value = 'two', uvalue = 'twoness')
six = WIDGET_BUTTON(base, value = 'six', uvalue = 'sixness')
ten = WIDGET_BUTTON(base, value = 'ten', uvalue = 'tenness')
; We will need this info when we set the value
WIDGET_CONTROL, base, $
SET_UVALUE = {propsheet:e.id, $
component:e.component, $
identifier:e.identifier}
WIDGET_CONTROL, base, /REALIZE
XMANAGER, 'UserDefEvent', base, event_handler = 'UserDefEvent'
END
;================================================
; (3) Event handlers and main widget program.
;------------------------------------------------
;
; Event handling code for the main widget program and
; the main widget program.
;------------------------------------------------
; prop_event
;
; The property sheet generates an event whenever the user changes
; a value. The event holds the property's identifier and type, and
; an object reference to the component.
;
; Note: widget_control, e.id, get_value = objref also retrieves an
; object reference to the component.
PRO prop_event, e
IF (e.type eq 0) THEN BEGIN ; Value changed
; Get the value of the property identified by e.identifier.
IF (e.proptype ne 0) THEN BEGIN
; Get the value from the property sheet.
value = widget_info(e.id, property_value = e.identifier)
; Set the component's property's value.
e.component->SetPropertyByIdentifier, e.identifier, $
value
; Print the change in the component's property value.
PRINT, 'Changed', e.identifier, ': ', value
ENDIF ELSE BEGIN
; Use alternative means to get the value.
GetUserDefValue, e
ENDELSE
ENDIF ELSE BEGIN ; selection changed
PRINT, 'Selected: ' + e.identifier
r = e.component->GetPropertyByIdentifier(e.identifier, value)
PRINT, ' Current Value: ', value
ENDELSE
END
;------------------------------------------------
PRO refresh_event, e
WIDGET_CONTROL, e.id, get_uvalue = uvalue
uvalue.o->SetProperty, boolean = 0L
uvalue.o->SetProperty, color = [255, 0, 46]
uvalue.o->SetPropertyAttribute, 'userdef', userdef = "Yeehaw!"
uvalue.o->SetProperty, number1 = 99L
uvalue.o->SetProperty, number2 = -13.1
uvalue.o->SetProperty, number3 = 6.5
uvalue.o->SetProperty, linestyle = 6L
uvalue.o->SetProperty, stringola = 'It worked!'
uvalue.o->SetProperty, stringlist = 6L
uvalue.o->SetProperty, symbol = 6L
uvalue.o->SetPropertyAttribute, 'Number1', sensitive = 1
uvalue.o->SetPropertyAttribute, 'Number2', sensitive = 1
WIDGET_CONTROL, uvalue.prop, $
REFRESH_PROPERTY = ['boolean', 'color', 'userdef', $
'number1', 'number2', 'number3', 'linestyle', $
'stringola', 'stringlist', 'symbol']
END
;------------------------------------------------
; reload_event
PRO reload_event, e
WIDGET_CONTROL, e.id, GET_UVALUE = uvalue
LoadValues, uvalue.o
WIDGET_CONTROL, uvalue.prop, SET_VALUE = uvalue.o
update_state, e.top, 1
END
;------------------------------------------------
PRO hide_event, e
WIDGET_CONTROL, e.id, get_uvalue = uvalue
uvalue.o->SetPropertyAttribute, 'color', HIDE
WIDGET_CONTROL, uvalue.prop, refresh_property = 'color'
END
;------------------------------------------------
PRO show_event, e
WIDGET_CONTROL, e.id, get_uvalue = uvalue
uvalue.o->SetPropertyAttribute, 'color', hide = 0
WIDGET_CONTROL, uvalue.prop, REFRESH_PROPERTY = 'color'
END
;------------------------------------------------
PRO clear_event, e
update_state, e.top, 0
WIDGET_CONTROL, e.id, GET_UVALUE = uvalue
WIDGET_CONTROL, uvalue.prop, SET_VALUE = SET_VALUE()
END
;------------------------------------------------
; psdemo_large_event
;
; Handles resize events for the property sheet demo program.
PRO psdemo_large_event, e
WIDGET_CONTROL, e.id, GET_UVALUE = base
geo_tlb = WIDGET_INFO(e.id, /GEOMETRY)
WIDGET_CONTROL, base.prop, $
SCR_XSIZE = geo_tlb.xsize - (2*geo_tlb.xpad), $
SCR_YSIZE = geo_tlb.ysize - (2*geo_tlb.ypad)
END
;------------------------------------------------
;
; Procedure to test sensitizing and desensitizing
PRO sensitivity_event, e
WIDGET_CONTROL, e.id, GET_UVALUE = uvalue, GET_VALUE = value
IF (value eq 'Desensitize') THEN b = 0 $
ELSE b = 1
uvalue.o->SetPropertyAttribute, 'Boolean', sensitive = b
uvalue.o->SetPropertyAttribute, 'Color', sensitive = b
uvalue.o->SetPropertyAttribute, 'UserDef', sensitive = b
uvalue.o->SetPropertyAttribute, 'Number1', sensitive = b
uvalue.o->SetPropertyAttribute, 'Number2', sensitive = b
uvalue.o->SetPropertyAttribute, 'Number3', sensitive = b
uvalue.o->SetPropertyAttribute, 'LineStyle', sensitive = b
uvalue.o->SetPropertyAttribute, 'LineThickness', sensitive = b
uvalue.o->SetPropertyAttribute, 'Stringola', sensitive = b
uvalue.o->SetPropertyAttribute, 'Symbol', sensitive = b
uvalue.o->SetPropertyAttribute, 'StringList', sensitive = b
WIDGET_CONTROL, uvalue.prop, $
refresh_property = ['Boolean', 'Color', 'UserDef', $
'Number1', 'Number2', 'Number3', 'LineStyle', $
'LineThickness', 'Stringola', 'Symbol', 'StringList']
END
;------------------------------------------------
PRO LoadValues, o
o->SetProperty, boolean = 1L ; 0 or 1
o->SetProperty, color = [200, 100, 50] ; RGB
o->SetPropertyAttribute, 'userdef', userdef = ""
; to be set later
o->SetProperty, number1 = 42L ; integer
o->SetProperty, number2 = 0.0 ; double
o->SetProperty, number3 = 0.1 ; double
o->SetProperty, linestyle = 4L ; 5th item (zero based)
o->SetProperty, linethickness = 4L ; pixels
o->SetProperty, stringola = "This is a silly string."
o->SetProperty, stringlist = 3L ; 4th item in list
o->SetProperty, symbol = 4L ; 5th symbol in list
END
;------------------------------------------------
PRO quit_event, e
WIDGET_CONTROL, e.top, DESTROY
END
;------------------------------------------------
; update_state
PRO update_state, top, sensitive
WIDGET_CONTROL, top, GET_UVALUE = uvalue
FOR i = 0, n_elements(uvalue.b) - 1 do $
WIDGET_CONTROL, uvalue.b[i], sensitive = sensitive
END
;------------------------------------------------
; psdemo_large
PRO psdemo_large
; Create and initialize the component.
o = OBJ_NEW('IDLitTester')
LoadValues, o
; Create some widgets.
base = WIDGET_BASE(/COLUMN, /TLB_SIZE_EVENT, $
TITLE = 'Property Sheet Demo (Large)')
prop = WIDGET_PROPERTYSHEET(base, value = o, $
YSIZE = 13, /FRAME, event_pro = 'prop_event')
b1 = WIDGET_BUTTON(base, value = 'Refresh', $
uvalue = {o:o, prop:prop}, $
event_pro = 'refresh_event')
b2 = WIDGET_BUTTON(base, value = 'Reload', $
uvalue = {o:o, prop:prop}, $
event_pro = 'reload_event')
b3 = WIDGET_BUTTON(base, value = 'Hide Color', $
uvalue = {o:o, prop:prop}, $
event_pro = 'hide_event')
b4 = WIDGET_BUTTON(base, value = 'Show Color', $
uvalue = {o:o, prop:prop}, $
event_pro = 'show_event')
b5 = WIDGET_BUTTON(base, value = 'Clear', $
uvalue = {o:o, prop:prop}, $
event_pro = 'clear_event')
b6 = WIDGET_BUTTON(base, value = 'Desensitize', $
uvalue = {o:o, prop:prop}, $
event_pro = 'sensitivity_event')
b7 = WIDGET_BUTTON(base, value = 'Sensitize', $
uvalue = {o:o, prop:prop}, $
event_pro = 'sensitivity_event')
b8 = WIDGET_BUTTON(base, value = 'Quit', $
EVENT_PRO = 'quit_event')
; Buttons that can't be pushed after clearing:
b = [b1, b3, b4, b5, b6, b7]
; Activate the widgets.
WIDGET_CONTROL, base, SET_UVALUE = {prop:prop, b:b}, /REALIZE
XMANAGER, 'psdemo_large', base, /NO_BLOCK
END
The following figure displays the output of this example, as user-defined property sheet:
To demonstrate the controls available from the WIDGET_PROPERTYSHEET, do the following and note the Selected and Changed messages in the IDL Output Log:
Click the eight buttons at the bottom of the property sheet to initiate the following events: